java中比较器Comparator的使用(结合PriorityQueue)

您所在的位置:网站首页 java中 override的用法 java中比较器Comparator的使用(结合PriorityQueue)

java中比较器Comparator的使用(结合PriorityQueue)

2024-01-23 17:24| 来源: 网络整理| 查看: 265

上期我们简单的介绍了下java中的排序接口Comparable的使用,由于Comparable是不够灵活的一种排序接口,它要去修改对象的类的代码。所以,我们今天介绍一款较为灵活的比较器接口Comparator。

首先,还是创建一个实体类Person2:

public class Person2 { private int age; private String name; private int xuehao; public Person2() { } public Person2(int age, String name, int xuehao) { this.age = age; this.name = name; this.xuehao = xuehao; } public int getXuehao() { return xuehao; } public void setXuehao(int xuehao) { this.xuehao = xuehao; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person2{" + "age=" + age + ", name='" + name + '\'' + ", xuehao=" + xuehao + '}'; } }

然后在我们的创作一个测试类Mytest:

public class Mytest { public static void main(String[] args) { Person2[] person2s = {new Person2(15,"张三",34), new Person2(5, "李四",12), new Person2(10, "王五",88)}; //创建比较器对象cp Comparator cp = new Comparator() { @Override//重写compare方法,使按照xuehao升序 //o2.getXuehao()-o1.getXuehao():按照xuehao降序 public int compare(Person2 o1, Person2 o2) { return o1.getXuehao()-o2.getXuehao(); } }; System.out.println("排序前:"); for(Person2 p:person2s){ System.out.println(p.toString()); } //对数组person2s安装比较器cp进行排序 Arrays.sort(person2s, cp); System.out.println("排序后:"); for(Person2 p:person2s){ System.out.println(p.toString()); } } }

运行结果如下:(按照xuehao升序)

排序前: Person2{age=15, name='张三', xuehao=34} Person2{age=5, name='李四', xuehao=12} Person2{age=10, name='王五', xuehao=88} 排序后: Person2{age=5, name='李四', xuehao=12} Person2{age=15, name='张三', xuehao=34} Person2{age=10, name='王五', xuehao=88}

当然,你也可以修改比较器中的compare方法,使其安装age降序,具体修改如下:

//创建比较器对象cp Comparator cp = new Comparator() { @Override//重写compare方法,使按照age降序 public int compare(Person2 o1, Person2 o2) { //若为o1.getAge()-o2.getAge():按照age升序 return o2.getAge()-o1.getAge(); } };

修改后,运行结果如下:

排序前: Person2{age=15, name='张三', xuehao=34} Person2{age=5, name='李四', xuehao=12} Person2{age=10, name='王五', xuehao=88} 排序后: Person2{age=15, name='张三', xuehao=34} Person2{age=10, name='王五', xuehao=88} Person2{age=5, name='李四', xuehao=12}

可以发现我们修改person2的排序方式并不用去修改person2中的代码,所以说Comparator比Comparable更加的灵活。

最后我们看下Comparator在优先队列中的使用,我们修改Mytest中的代码如下:

public class Mytest { public static void main(String[] args) { //创建一个比较器 Comparator cp = new Comparator() { @Override public int compare(Person2 o1, Person2 o2) { //安照年龄升序 return o1.getAge()-o2.getAge(); } }; //将比较器cp作为参数创建一个优先队列 PriorityQueue priorityQueue = new PriorityQueue(cp); //往队列中加入数据 priorityQueue.add(new Person2(15,"张三",2)); priorityQueue.add(new Person2(33,"张三",78)); priorityQueue.add(new Person2(1,"张三",33)); priorityQueue.add(new Person2(5, "李四",14)); priorityQueue.add(new Person2(55,"张三",35)); priorityQueue.add(new Person2(10, "王五",22)); System.out.println("遍历优先队列:"); for(Person2 p:priorityQueue){ System.out.println(p.toString()); } System.out.println("依次弹出优先队列中的值"); while(!priorityQueue.isEmpty()){ System.out.println(priorityQueue.poll()); } } }

运行结果如下:

遍历优先队列: Person2{age=1, name='张三', xuehao=33} Person2{age=5, name='李四', xuehao=14} Person2{age=10, name='王五', xuehao=22} Person2{age=33, name='张三', xuehao=78} Person2{age=55, name='张三', xuehao=35} Person2{age=15, name='张三', xuehao=2} 依次弹出优先队列中的值 Person2{age=1, name='张三', xuehao=33} Person2{age=5, name='李四', xuehao=14} Person2{age=10, name='王五', xuehao=22} Person2{age=15, name='张三', xuehao=2} Person2{age=33, name='张三', xuehao=78} Person2{age=55, name='张三', xuehao=35}

显然,重结果中我们可以看出,优先队列弹出元素的顺序是按照age升序的。同时,细心的同学可以从我们的遍历结果中发现,优先队列中各个元素是按照其年龄(age)值来维护了一个完全二叉树的小顶堆,如下图所示:(节点中为各个元素age的值)

 

下面我们去修改比较器,具体代码如下:

//创建一个比较器 Comparator cp = new Comparator() { @Override public int compare(Person2 o1, Person2 o2) { //按照xuehao降序 return o2.getXuehao()-o1.getXuehao(); } };

 然后再运行,得到如下结果:

遍历优先队列: Person2{age=33, name='张三', xuehao=78} Person2{age=55, name='张三', xuehao=35} Person2{age=1, name='张三', xuehao=33} Person2{age=15, name='张三', xuehao=2} Person2{age=5, name='李四', xuehao=14} Person2{age=10, name='王五', xuehao=22} 依次弹出优先队列中的值 Person2{age=33, name='张三', xuehao=78} Person2{age=55, name='张三', xuehao=35} Person2{age=1, name='张三', xuehao=33} Person2{age=10, name='王五', xuehao=22} Person2{age=5, name='李四', xuehao=14} Person2{age=15, name='张三', xuehao=2}

此时我们可以发现我们元素的弹出顺序是按照xuehao降序的,而遍历的结果是按照xuehao来维护的一个大顶堆(如下图 )。

至此,我们可以总结为如下:

在优先队列中,如果定义的比较器是按照某值X升序(return o1.X-o2.X)排序的,那么优先队列中元素的位置会按照X的值所构建的小顶堆来放置;

在优先队列中,如果定义的比较器是按照某值X降序(return o2.X-o1.X)排序的,那么优先队列中元素的位置会按照X的值所构建的大顶堆来放置;

在使用比较器的时候,你也可以先创建一个比较器的类,然后在要使用的时候去new一个该类的对象也可以。比如在我们例子中,我们可以去创建下面这个类:

public class MyComparator implements Comparator { @Override public int compare(Person2 o1, Person2 o2) { //按照年龄age升序 return o1.getAge()-o2.getAge(); } }

然后在使用的时候直接去创建该类的对象,可以将我们的测试类的代码修改如下部分:

//创建一个比较器 // Comparator cp = new Comparator() { // @Override // public int compare(Person2 o1, Person2 o2) { // //按照xuehao降序 // return o2.getXuehao()-o1.getXuehao(); // } // }; //此处比较器的排序规则要到MyComparator中去查看或修改 MyComparator cp = new MyComparator();

比较器接口Comparator的介绍到此就暂告一段落了,若文中有描述不当之处,希望大家多多指出,我们一起学习一起进步。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3